{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 说明\n",
    "\n",
    "在开发环境中将目录中的 `model目录/V版本`，`notebook目录` 进行 Sync Obs 同步，之后在下面代码里修改同步模型的版本号。\n",
    "\n",
    "\n",
    "- `model目录/V版本` 中可能含有多个版本，只需要选择需要调试的版本目录进行同步即可\n",
    "\n",
    "- `notebook目录` 中含 `detect_image.py文件` 和 `detect_video.py文件` 是便于自己本机运行和在开发环境 `Terminal - TensorFlow-1.13.1` 中执行。\n",
    "\n",
    "在 `Terminal` 中使用命令 `source /home/ma-user/anaconda3/bin/activate TensorFlow-1.13.1` 可以切换到 `TensorFlow-1.13.1` 的环境方便运行\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 查看同步的模型目录和调试所需文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!ls -lh model/V0025/model\n",
    "\n",
    "!ls -lh notebook"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 图片识别 `detect_image.py` 文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!python notebook/detect_image.py --image notebook/test.jpg --min_score 0.2 --show_image true --show_box_label true --input_size 1024 --version V0025 --h5 train_mask_rcnn.h5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 视频识别 `detect_video.py` 文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!python notebook/detect_video.py --video notebook/test.mp4 --min_score 0.2 --show_image true --show_box_label true --input_size 1024 --version V0025 --h5 train_mask_rcnn.h5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 下面是便于观察的ipynb调试\n",
    "\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 开始\n",
    "\n",
    "detect_image.py文件 和 detect_video.py文件，所需模型依赖。\n",
    "\n",
    "**参数配置**\n",
    "\n",
    "- version 模型对应版本\n",
    "- h5 模型文件名\n",
    "- input_size 统一输入图像大小\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os, sys\n",
    "import tensorflow as tf\n",
    "from moxing.framework import file\n",
    "import cv2.cv2\n",
    "import time\n",
    "\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt \n",
    "\n",
    "# 参数配置\n",
    "version = 'V0025' # 模型版本 \n",
    "h5 = 'train_mask_rcnn.h5' # 模型文件\n",
    "input_size = 1024 # 统一输入图像大小\n",
    "\n",
    "# 执行所在路径， V0xxx 表示模型版本号\n",
    "source_path = os.path.join(os.getcwd(), \"model/\" + version + \"/model\")\n",
    "sys.path.append(source_path)\n",
    "\n",
    "from draw import model_load, display_instances, sliceImage, image_to_base64\n",
    "\n",
    "# 选择输出绘制类识别80类，\n",
    "COCO_CLASSES = ['BG', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',\n",
    "                'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign',\n",
    "                'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',\n",
    "                'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag',\n",
    "                'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite',\n",
    "                'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket',\n",
    "                'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',\n",
    "                'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',\n",
    "                'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',\n",
    "                'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock',\n",
    "                'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']\n",
    "\n",
    "# 模型权重文件\n",
    "COCO_MODEL_PATH = os.path.join(source_path, h5)\n",
    "\n",
    "# 加载模型\n",
    "model = model_load(COCO_MODEL_PATH, input_size)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 图片识别\n",
    "\n",
    "detect_image.py 文件内部代码\n",
    "\n",
    "**参数配置**\n",
    "\n",
    "- image 用于识别图文件\n",
    "- min_score 显示最低分数 \n",
    "- show_image 显示图片\n",
    "- show_box_label 显示标识边框标签\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 参数配置\n",
    "image = cv2.imread('notebook/test.jpg') # 用于识别图文件\n",
    "image_orig = image.copy() # 用于分割小图的原图\n",
    "min_score = 0.2 # 显示最低分数\n",
    "show_image = True # 显示图片beas64\n",
    "show_box_label = True # 显示标识边框标签 \n",
    "\n",
    "created_at = str(round(time.time() * 1000))\n",
    "\n",
    "# obs桶路径\n",
    "obs_path = \"obs://puddings/ma-mask-rcnn/notebook/out/image/\" + created_at\n",
    "\n",
    "# 输出目录\n",
    "out_path = \"notebook/out/image/\" + created_at\n",
    "\n",
    "# 输出目录存在需要删除里边的内容\n",
    "if os.path.exists(out_path):\n",
    "    file.remove(out_path, recursive=True)\n",
    "os.makedirs(out_path)\n",
    "\n",
    "prev_time = time.time()\n",
    "# 模型识别结果 rois, masks, class_ids, scores\n",
    "results = model.detect([image], verbose=0)[0]\n",
    "    \n",
    "# 结果绘制到图\n",
    "image, recognizer = display_instances(\n",
    "    image,\n",
    "    results,\n",
    "    COCO_CLASSES,\n",
    "    min_score,\n",
    "    show_image,\n",
    "    show_box_label\n",
    ")\n",
    "\n",
    "# 绘制时间\n",
    "curr_time = time.time()\n",
    "exec_time = curr_time - prev_time\n",
    "print(\"识别耗时: %.2f ms\" %(1000*exec_time))\n",
    "\n",
    "# print(\"识别结果：\", recognizer)\n",
    "\n",
    "# 输入图片np uint8 尺寸/2\n",
    "# x, y = image.shape[0:2]\n",
    "# image = cv2.resize(image, (int(y / 2), int(x / 2)))\n",
    "\n",
    "# base图片编码\n",
    "# itb64 = image_to_base64(image)\n",
    "# print(itb64)\n",
    "\n",
    "# 绘制识别统计\n",
    "totalStr = \"\"\n",
    "for k in recognizer.keys():\n",
    "    totalStr += '%s: %d    ' % (k, len(recognizer[k]))\n",
    "cv2.putText(image, totalStr, (10,20), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (50, 0, 255), 1, cv2.LINE_AA)\n",
    "    \n",
    "# 绘制保存\n",
    "cv2.imwrite(out_path + \"/output_result.jpg\", image)\n",
    "cv2.imwrite(out_path + \"/output_orig.jpg\", image_orig)\n",
    "\n",
    "# 切割识别到的物体\n",
    "sliceImage(image_orig, recognizer, out_path)\n",
    "   \n",
    "# 复制保存到桶\n",
    "print(\"输出目录：\" + out_path)\n",
    "file.copy_parallel(out_path, obs_path)\n",
    "\n",
    "# 总图绘制显示ipynb\n",
    "result = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)\n",
    "plt.figure(figsize=(10,10))\n",
    "plt.imshow(result)\n",
    "plt.axis('on')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 视频识别\n",
    "\n",
    "detect_video.py 文件内部代码\n",
    "\n",
    "**参数配置**\n",
    "\n",
    "- video 视频文件 \n",
    "- min_score 显示最低分数 \n",
    "- show_image 显示图片\n",
    "- show_box_label 显示标识边框标签"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 参数配置\n",
    "video = cv2.VideoCapture('notebook/test.mp4') # 用于识别的视频文件 \n",
    "min_score = 0.2 # 显示最低分数\n",
    "show_image = True # 显示图片beas64\n",
    "show_box_label = True # 显示标识边框标签 \n",
    "\n",
    "# 输出目录\n",
    "out_path = \"notebook/out/video\"\n",
    "\n",
    "# 输出目录存在需要删除里边的内容\n",
    "if os.path.exists(out_path):\n",
    "    file.remove(out_path, recursive=True)\n",
    "os.makedirs(out_path)\n",
    "\n",
    "# 帧数，用于通过帧数取图\n",
    "frameNum = 0\n",
    "\n",
    "# 视频总帧统计物体数，存在重复\n",
    "totalCount = {}\n",
    "\n",
    "# obs桶路径\n",
    "obs_path = \"obs://puddings/ma-mask-rcnn/notebook/out/video\"\n",
    "\n",
    "# 保存统计总数并复制保存到桶\n",
    "def outTotalObs(totalCount, out_path, obs_path):\n",
    "    # 打开文件进行视频识别物总统计\n",
    "    totalFile = open(out_path + \"/totalCount.txt\",\"w\")\n",
    "    # 文件统计写入\n",
    "    for k in totalCount.keys():\n",
    "        labelStr = \"{0}：{1} \\n\".format(k, totalCount[k])\n",
    "        totalFile.write(labelStr)\n",
    "     # 关闭文件统计        \n",
    "    totalFile.close()\n",
    "    # 复制保存到桶\n",
    "    file.copy_parallel(out_path, obs_path)\n",
    "\n",
    "# 输出保存视频\n",
    "fourcc = cv2.VideoWriter_fourcc(*'XVID')\n",
    "fps = video.get(cv2.CAP_PROP_FPS)\n",
    "size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)))\n",
    "video_out = cv2.VideoWriter(out_path + \"/outputVideo.mp4\", fourcc, fps, size)\n",
    "\n",
    "# 视频是否可以打开，进行逐帧识别绘制\n",
    "while video.isOpened:\n",
    "    # 视频读取图片帧\n",
    "    retval, frame = video.read()\n",
    "    if retval:\n",
    "        frame_orig = frame.copy()\n",
    "        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n",
    "    else:\n",
    "        # 保存统计总数并复制保存到桶\n",
    "        outTotalObs(totalCount, out_path, obs_path)\n",
    "        # 读取失败、结束后释放所有内容\n",
    "        video.release()\n",
    "        video_out.release()\n",
    "        print(\"没有图像！尝试使用其他视频\")\n",
    "        break\n",
    "\n",
    "    print('识别帧：%d/%d' % (frameNum, video.get(7)))\n",
    "    prev_time = time.time()\n",
    "    # 模型识别结果 rois, masks, class_ids, scores\n",
    "    results = model.detect([frame], verbose=0)[0]\n",
    "\n",
    "    # 结果绘制到图\n",
    "    image, recognizer = display_instances(\n",
    "        frame,\n",
    "        results,\n",
    "        COCO_CLASSES,\n",
    "        min_score,\n",
    "        show_image,\n",
    "        show_box_label\n",
    "    )\n",
    "\n",
    "    # 绘制时间\n",
    "    curr_time = time.time()\n",
    "    exec_time = curr_time - prev_time\n",
    "    print(\"识别耗时: %.2f ms\" %(1000*exec_time))\n",
    "        \n",
    "    # print(\"识别结果：\", recognizer)\n",
    "    \n",
    "    # 遍历识别数据并绘制帧识别统计\n",
    "    totalStr = \"\"\n",
    "    for k in recognizer.keys():\n",
    "        if k not in totalCount: totalCount[k] = 0\n",
    "        num = len(recognizer[k]);\n",
    "        totalCount[k] += num\n",
    "        totalStr += '%s: %d    ' % (k, num)\n",
    "        cv2.putText(image, totalStr, (10,20), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (50, 0, 255), 1, cv2.LINE_AA)\n",
    "\n",
    "    # 视频输出保存\n",
    "    result = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)\n",
    "    video_out.write(result)\n",
    "    \n",
    "    # 每300帧取图进行分割保存\n",
    "    if(frameNum % 300 == 0):\n",
    "        # 输出帧目录,不存目录需要创建\n",
    "        slice_path = os.path.join(out_path, \"imageSeg-\" + str(frameNum))\n",
    "        if not os.path.exists(slice_path):\n",
    "            os.makedirs(slice_path)\n",
    "        # 绘制帧保存\n",
    "        cv2.imwrite(os.path.join(slice_path, \"output_result.jpg\"), result)\n",
    "        cv2.imwrite(os.path.join(slice_path, \"output_orig.jpg\"), frame_orig)\n",
    "        # 切割识别到的物体\n",
    "        sliceImage(frame_orig, recognizer, slice_path)\n",
    "    frameNum += 1\n",
    "\n",
    "    # 保存统计总数并复制保存到桶\n",
    "    outTotalObs(totalCount, out_path, obs_path)\n",
    "\n",
    "    # 绘制结果ipynb显示\n",
    "    plt.figure(figsize=(10,10))\n",
    "    plt.imshow(image)\n",
    "    plt.axis('on')\n",
    "    plt.show()\n",
    "\n",
    "# 保存统计总数并复制保存到桶\n",
    "print(\"输出目录：\" + out_path)\n",
    "outTotalObs(totalCount, out_path, obs_path)\n",
    "\n",
    "# 任务完成后释放所有内容\n",
    "video.release()\n",
    "video_out.release()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7-final"
  },
  "orig_nbformat": 2,
  "kernelspec": {
   "name": "python37764bit9b2c3154938c4f1ebde4a7670bed1c22",
   "display_name": "Python 3.7.7 64-bit"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}